﻿// -----------------------------------------------------------------------
// <copyright file="BinaryWriterEx.cs" company="none">
// Copyright (c) 2012 M. Alberti, xanatos(at)live.it
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// </copyright>
// -----------------------------------------------------------------------

namespace FluentSerializer.Utilities
{
    using System;
    using System.IO;

    /// <summary>
    /// 
    /// </summary>
    public static class BinaryWriterEx
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        public static void Write(this BinaryWriter writer, IntPtr value)
        {
            if (IntPtr.Size == sizeof(int))
            {
                writer.Write(new PrimitiveTypeConverter { IntPtr = value }.UInt32A);
            }
            else
            {
                writer.Write(new PrimitiveTypeConverter { IntPtr = value }.UInt64);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        public static void Write(this BinaryWriter writer, UIntPtr value)
        {
            if (IntPtr.Size == sizeof(int))
            {
                writer.Write(new PrimitiveTypeConverter { UIntPtr = value }.UInt32A);
            }
            else
            {
                writer.Write(new PrimitiveTypeConverter { UIntPtr = value }.UInt64);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, bool[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, short[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, ushort[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, int[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, uint[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, long[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, ulong[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, float[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, double[] buffer, int offset, int count)
        {
            count += offset;

            for (int i = offset; i < count; i++)
            {
                writer.Write(buffer[i]);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, IntPtr[] buffer, int offset, int count)
        {
            var ptc = new PrimitiveTypeConverter();

            count += offset;

            if (IntPtr.Size == sizeof(int))
            {
                for (int i = offset; i < count; i++)
                {
                    ptc.IntPtr = buffer[i];
                    writer.Write(ptc.UInt32A);
                }
            }
            else
            {
                for (int i = offset; i < count; i++)
                {
                    ptc.IntPtr = buffer[i];
                    writer.Write(ptc.UInt64);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, UIntPtr[] buffer, int offset, int count)
        {
            var ptc = new PrimitiveTypeConverter();

            count += offset;

            if (IntPtr.Size == sizeof(int))
            {
                for (int i = offset; i < count; i++)
                {
                    ptc.UIntPtr = buffer[i];
                    writer.Write(ptc.UInt32A);
                }
            }
            else
            {
                for (int i = offset; i < count; i++)
                {
                    ptc.UIntPtr = buffer[i];
                    writer.Write(ptc.UInt64);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="buffer"></param>
        /// <param name="sizeElement"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public static void Write(this BinaryWriter writer, Array buffer, int sizeElement, int offset, int count)
        {
            if (sizeElement == 1 && buffer is byte[])
            {
                writer.Write((byte[])buffer, offset, count);
                return;
            }

            offset *= sizeElement;
            count *= sizeElement;

            var buffer2 = new byte[sizeElement * count];
            System.Buffer.BlockCopy(buffer, offset, buffer2, 0, count);
            writer.Write(buffer2, 0, buffer2.Length);
        }
    }
}